package com.tanhua.dubbo.api.impl.mongo;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
import com.tanhua.domain.mongo.Friend;
import com.tanhua.domain.mongo.UserLike;
import com.tanhua.domain.mongo.Visitors;
import com.tanhua.domain.vo.PageResult;
import com.tanhua.dubbo.api.mongo.RecommendUserApi;
import com.tanhua.dubbo.api.mongo.UserLikeApi;
import org.apache.dubbo.config.annotation.Service;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;


import java.util.*;

@Service(timeout = 200000)
public class UserLikeApiImpl implements UserLikeApi {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private RecommendUserApi recommendUserApi;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    public static final String LIKE_REDIS_KEY_PREFIX = "USER_LIKE_";

    public static final String NOT_LIKE_REDIS_KEY_PREFIX = "USER_NOT_LIKE_";



    @Override
    public Long queryEachLoveCount(Long userId) {
        // 查询统计互相喜欢 db.tanhua_users.find({userId:1})
        Query query = Query.query(Criteria.where("userId").is(userId));
        return mongoTemplate.count(query, Friend.class);
    }

    @Override
    public Long queryLoveCount(Long userId) {
        // 查询统计喜欢 db.user_like.find({userId:1})
        Query query = Query.query(Criteria.where("userId").is(userId));
        return mongoTemplate.count(query, UserLike.class);
    }

    @Override
    public Long queryFanCount(Long userId) {
        // 查询统计粉丝 db.user_like.find({likeUserId:1})
        Query query = Query.query(Criteria.where("likeUserId").is(userId));
        return mongoTemplate.count(query, UserLike.class);
    }

    @Override
    public PageResult queryEachLoveList(Long userId, Integer page, Integer pagesize) {
        // 互相关注  db.tanhua_users.find({userId:1})
        // 条件
        Query query = Query.query(Criteria.where("userId").is(userId))
                .skip((page-1)*pagesize)
                .limit(pagesize);
        // 分页查询
        List<Friend> friendList = mongoTemplate.find(query, Friend.class);
        long count = mongoTemplate.count(query, Friend.class);
        // 通过List<Map<String,Object>>封装返回的结果
        List<Map<String,Object>> list = new ArrayList<>();
        if (friendList != null && friendList.size()>0) {
            Map<String,Object> map = null;
            for (Friend friend : friendList) {
                map = new HashMap<>();
                map.put("userId",friend.getFriendId());
                map.put("score",recommendUserApi.queryScore(friend.getUserId(),friend.getFriendId()));
                list.add(map);
            }
        }
        return new PageResult(page,pagesize, (int) count,list);
    }

    @Override
    public PageResult queryLoveList(Long userId, Integer page, Integer pagesize) {
         // 我关注  db.user_like.find({userId:1})
        Query query = Query.query(Criteria.where("userId").is(userId))
                .skip((page-1)*pagesize)
                .limit(pagesize);
        List<UserLike> userLikeList = mongoTemplate.find(query, UserLike.class);
        long count = mongoTemplate.count(query, UserLike.class);

        // 通过List<Map<String,Object>>封装返回的结果
        List<Map<String,Object>> list = new ArrayList<>();
        if (userLikeList != null && userLikeList.size()>0) {
            Map<String,Object> map = null;
            for (UserLike userLike : userLikeList) {
                map = new HashMap<>();
                map.put("userId",userLike.getLikeUserId());
                map.put("score",recommendUserApi.queryScore(userLike.getUserId(),userLike.getLikeUserId()));
                list.add(map);
            }
        }
        return new PageResult(page,pagesize, (int) count,list);
    }

    @Override
    public PageResult queryFanList(Long userId, Integer page, Integer pagesize) {
        // 粉丝  db.user_like.find({likeUserId:1})
        Query query = Query.query(Criteria.where("likeUserId").is(userId))
                .skip((page-1)*pagesize)
                .limit(pagesize);
        List<UserLike> userLikeList = mongoTemplate.find(query, UserLike.class);
        long count = mongoTemplate.count(query, UserLike.class);

        // 通过List<Map<String,Object>>封装返回的结果
        List<Map<String,Object>> list = new ArrayList<>();
        if (userLikeList != null && userLikeList.size()>0) {
            Map<String,Object> map = null;
            for (UserLike userLike : userLikeList) {
                map = new HashMap<>();
                map.put("userId",userLike.getUserId());
                map.put("score",recommendUserApi.queryScore(userLike.getLikeUserId(),userLike.getUserId()));
                list.add(map);
            }
        }
        return new PageResult(page,pagesize, (int) count,list);
    }

    @Override
    public PageResult queryVistorsList(Long userId, Integer page, Integer pagesize) {
        // 谁看过我 db.visitors.find({userId:1}).sort({date:-1})
        Query query = Query.query(Criteria.where("userId").is(userId))
                .with(Sort.by(Sort.Order.desc("date")))
                .skip((page-1)*pagesize)
                .limit(pagesize);
        List<Visitors> visitorsList = mongoTemplate.find(query, Visitors.class);
        long count = mongoTemplate.count(query, Visitors.class);

        // 通过List<Map<String,Object>>封装返回的结果
        List<Map<String,Object>> list = new ArrayList<>();
        if (visitorsList != null && visitorsList.size()>0) {
            Map<String,Object> map = null;
            for (Visitors visitors : visitorsList) {
                map = new HashMap<>();
                map.put("userId",visitors.getVisitorUserId());
                map.put("score",recommendUserApi.queryScore(visitors.getUserId(),visitors.getVisitorUserId()));
                list.add(map);
            }
        }
        return new PageResult(page,pagesize, (int) count,list);
    }

    @Override
    public void delete(Long userId, Long likeUserId) {
        //* 删除粉丝中的喜欢数据 db.user_like.remove({likeUserId:1,userId:23})
        Query query = new Query(
            Criteria.where("userId").is(likeUserId)
                .and("likeUserId").is(userId)
        );
        mongoTemplate.remove(query,UserLike.class);
    }

    /**
     * 获取喜欢
     */
    private String getLikeRedisKey(Long userId){
        return LIKE_REDIS_KEY_PREFIX + userId;
    }

    /**
     * 获取不喜欢
     */
    private String getNotLikeRedisKey(Long userId){
        return NOT_LIKE_REDIS_KEY_PREFIX + userId;
    }
    /**
     * 是否喜欢
     *
     * @param userId
     * @param likeUserId
     * @return
     */
    private Boolean isLike(Long userId, Long likeUserId){
        String redisKey = getLikeRedisKey(userId);
        String hashKey = String.valueOf(likeUserId);
        return redisTemplate.opsForHash().hasKey(redisKey, hashKey);
    }

    /**
     * 是否不喜欢
     *
     * @param userId
     * @param likeUserId
     * @return
     */
    private Boolean isNotLike(Long userId, Long likeUserId){
        String redisKey = getNotLikeRedisKey(userId);
        String hashKey = String.valueOf(likeUserId);
        return redisTemplate.opsForHash().hasKey(redisKey, hashKey);
    }

    //探花-喜欢
    @Override
    public Boolean likeUser(Long userId, Long likeUserId) {
        //判断该用户是否已经喜欢，如果已经喜欢就返回
        if(isLike(userId, likeUserId)){
            return false;
        }

        UserLike userLike = new UserLike();
        userLike.setId(ObjectId.get());
        userLike.setUserId(userId);
        userLike.setLikeUserId(likeUserId);
        userLike.setCreated(System.currentTimeMillis());

        //将数据存储到MongoDB
        Query query = Query.query(
                Criteria.where("userId").is(userId)
                        .and("friendId").is(likeUserId)
        );

        if (!mongoTemplate.exists(query, Friend.class)){
            mongoTemplate.save(userLike);
        }

        //用户的喜欢数据保存到redis
        String redisKey = getLikeRedisKey(userId);
        String hashKey = String.valueOf(likeUserId);
        redisTemplate.opsForHash().put(redisKey, hashKey, "1");

        //判断，喜欢的用户是否在不喜欢的列表中，如果在，就需要删除数据
        if(isNotLike(userId, likeUserId)){
            redisKey = getNotLikeRedisKey(userId);
            redisTemplate.opsForHash().delete(redisKey, hashKey);
        }

        return true;
    }

    //探花-不喜欢
    @Override
    public Boolean notLikeUser(Long userId, Long likeUserId) {
        //判断用户是否已经不喜欢，如果已经不喜欢，就返回
        if(isNotLike(userId, likeUserId)){
            return false;
        }

        //将用户保存到不喜欢列表中
        String redisKey = getNotLikeRedisKey(userId);
        String hashKey = String.valueOf(likeUserId);
        redisTemplate.opsForHash().put(redisKey, hashKey, "1");

        //判断用户是否在喜欢列表中，如果存在的话，需要删除数据
        if(isLike(userId, likeUserId)){
            //删除MongoDB数据
            Query query = Query.query(Criteria
                    .where("userId").is(userId)
                    .and("likeUserId").is(likeUserId)
            );
           mongoTemplate.remove(query, UserLike.class);

            //删除redis中的数据
            redisKey = getLikeRedisKey(userId);
           redisTemplate.opsForHash().delete(redisKey, hashKey);
        }

        return true;
    }

    //是否相互喜欢
    @Override
    public Boolean isMutualLike(Long userId, Long likeUserId) {
        return isLike(userId,likeUserId) && isLike(likeUserId,userId) ;
    }

    //查询redis里喜欢列表
    @Override
    public List<Long> queryLikeList(Long userId) {
        // 查询redis
        String redisKey = getLikeRedisKey(userId);
        Set<Object> keys = redisTemplate.opsForHash().keys(redisKey);
        if(CollUtil.isEmpty(keys)){
            return ListUtil.empty();
        }

        List<Long> result = new ArrayList<>(keys.size());
        keys.forEach(o -> result.add(Convert.toLong(o)));
        return result;
    }

    //查询redis里不喜欢列表
    @Override
    public List<Long> queryNotLikeList(Long userId) {
        // 查询redis
        String redisKey = getNotLikeRedisKey(userId);
        Set<Object> keys = redisTemplate.opsForHash().keys(redisKey);
        if(CollUtil.isEmpty(keys)){
            return ListUtil.empty();
        }

        List<Long> result = new ArrayList<>(keys.size());
        keys.forEach(o -> result.add(Convert.toLong(o)));
        return result;
    }

    @Override
    public void unLike(Long userId, Long likeUserId) {
        Query query = new Query(
                Criteria.where("userId").is(userId)
                        .and("likeUserId").is(likeUserId)
        );
        mongoTemplate.remove(query,UserLike.class);
    }
}
